; Loads the file into RAM and executes it
; inputs	de = pointer to path
; outputs	a  = status code
ExecFile:
	call LoadFileToRAM
	if(SUCCESS)
		ret nz
	push de
		ld h,d \ ld l,e
		inc hl \ inc hl
		ld de,_ \ push de \ jp(hl)\_ ; call (hl)
	pop ix
	call FreeMem
	return(SUCCESS)
; Loads a file into RAM and returns the data
; inputs	de = Pointer to path
; outputs	de = pointer to file
;		bc = length of file
;		a  = status code
LoadFileToRAM:
	call SafeInterruptDI
	push af
		call GetFilePointer
#ifdef DEBUG
		push bc
			push de
				push af
					ld hl,ErrorCodeMsg
					push af
						call DrawWrappedString
					pop af
					call DispHexA
					call Newline
				pop af
			pop de
		pop bc
#endif
		if(SUCCESS)
			jr nz,++_
		ld h,d
		ld l,e
		inc hl \ inc hl		; skip the file size and get to the actual data
		dec bc \ dec bc		; decrease bc by that too btw
		call AllocateMem	; get the space in ram for it
#ifdef DEBUG
		push ix
			push hl
				push bc
					push af
						ld hl,ErrorCodeMsg
						push af
							call DrawWrappedString
						pop af
						call DispHexA
						call Newline
					pop af
				pop bc
			pop hl
		pop de
#endif
		if(ALLOCATE_SUCCESS)
			jr nz,++_
#ifndef DEBUG
		push ix
		pop de			; ld de,ix
#endif
		push de			; store the pointer
			push bc		; store the size
				ldir	; copy over the data
			pop bc		; recall the size
		pop de			; spit pointer out for use
	pop af
	jr c,$+3
	ei
_	return(SUCCESS)
_	ld b,a
	pop af
	jr c,$+3
	ei
	ld a,b
	ret
; Loads a file into RAM and returns the data
; inputs	de = Pointer to path
; outputs	de = pointer to file
;		bc = length of file
;		a  = status code
LoadExecutableToRAM:
	call SafeInterruptDI
	push af
	call GetFilePointer
#ifdef DEBUG
	push bc
		push de
			push af
				push af
					ld hl,ErrorCodeMsg
					call DrawWrappedString
				pop af
				call DispHexA
				call Newline
			pop af
		pop de
	pop bc
#endif
	if(SUCCESS)
		jr nz,++_
	inc de \ inc de			; skip the file size and get to the actual data
	dec bc \ dec bc \ dec bc	; decrease bc by that too btw and by one for the stack size byte
	ld a,(de)			; get the stack size byte
	inc de				; skip past the stack size byte
	add a,MaxDepth*2
	ld l,a
	ld h,0
	add hl,bc
	ld b,h
	ld c,l
	ld h,d
	ld l,e
	call AllocateMem	; get the space in ram for it
#ifdef DEBUG
	push ix
		push hl
			push bc
				push af
					ld hl,ErrorCodeMsg
					push af
						call DrawWrappedString
					pop af
					call DispHexA
					call Newline
				pop af
			pop bc
		pop hl
	pop de
#endif
	if(ALLOCATE_SUCCESS)
		jr nz,++_
#ifndef DEBUG
	push ix
	pop de			; ld de,ix
#endif
	push de			; store the pointer
		push bc		; store the size
			ldir	; copy over the data
		pop bc		; recall the size
	pop de			; spit it out for use
	pop af
	jr c,$+3
	ei
_	return(SUCCESS)
_	ld b,a
	pop af
	jr c,$+3
	ei
	ld a,b
	ret
; returns the pointer to the file from the path in de
; inputs	de = pointer to path string
; outputs	de = pointer to file
;		bc = length of file
;		a  = status code
;		h  = flash page
GetFilePointer:
#ifdef DEBUG
	push de
		ld hl,NameSearchMsg
		call DrawWrappedString
		ld h,d
		ld l,e
		call DrawWrappedString
		call Newline
	pop de
#endif
	ld hl,0
	ld (FSTmp),hl	; set the dir to root
	ld a, 1	; Set flash page 1 in bank 2.
	out (6), a
	push de
		ld hl,(FILE_START)
		ld de,FILE_START
		or a
		sbc hl,de
			jr z,_ ; if they are the same no corruption
		; corruption error here
		ld a,MEMORY_CORRUPT
	pop de
	ret
	
_	pop de ; memory is fine here
	ld hl,FILE_START+2
_DirLoop:
	call ContainsSlash
;		jr nz, ; Directory in path
		jp nz, _FileSearch_ ; no directory in path
	;handle directory searching here
	ld a, (hl)
#ifdef DEBUG
	push de
	       push hl
		       push bc
		               push af
		               	       push af
		               	              ld hl,TypeIDMsg
		               	              call DrawWrappedString
		               	       pop af
		                       call DispHexA
		                       call Newline
		               pop af
		       pop bc
	       pop hl
	pop de
#endif
	if(FILE_END) ; End of table
		jp z,_END_OF_TABLE ; Not found
	if(FILE_DIRECTORY) ; Directory
		jr z, _CheckDirectory
	if(FILE_FILE)
		jp nz,_BAD_PATH ; don't handle anything else for now
	call SkipFileEntry
	jr _DirLoop
_CheckDirectory:
#ifdef DEBUG
	push de
		push hl
			push bc
				push af
					push hl
						ld hl,NameDirMsg
						call DrawWrappedString
					pop hl
					inc hl
					call DrawWrappedString
					call Newline
				pop af
			pop bc
		pop hl
	pop de
#endif
	inc hl
	call DirectoryCompare
		jr nz, _DirNotFound
#ifdef DEBUG
	push hl
		push de
			ld hl,NameSearchMsg
			call DrawWrappedString
			ld h,d
			ld l,e
			call DrawWrappedString
			call Newline
		pop de
	pop hl
#endif
	push hl
		push de
			inc hl
			ld e,(hl)
			inc hl
			ld d,(hl)	; get Folder ID
			inc hl
			ld c,(hl)
			inc hl
			ld b,(hl)	; get Parent ID
			push de	; store the folder id
				ld hl,FSTmp
				ld e,(hl)
				inc hl
				ld d,(hl)	; get the last ID
				ld a,d
				cp b
					jr nz,_
				ld a,e
				cp c
					jr nz,_
			pop de
			dec hl
			ld (hl),e
			inc hl
			ld (hl),d	; store the new ID
			jr _+1
_			pop de	; recall it
		pop de
	pop hl
	call SkipDirEntry
	jp _DirLoop
_DirNotFound:
	call SkipDirEntry
	jp _DirLoop
_FileSearch_:
	ld hl,FILE_START+2
_FileSearch:
	ld a,(hl)	;get File type
#ifdef DEBUG
	push de
	       push hl
		       push bc
		               push af
		               	       push af
		               	              ld hl,TypeIDMsg
		               	              call DrawWrappedString
		               	       pop af
		                       call DispHexA
		                       call Newline
		                       call FastCopy
		               pop af
		       pop bc
	       pop hl
	pop de
#endif
	if(FILE_END) ; End of table
		jp z,_END_OF_TABLE ; Not found
	if(FILE_FILE) ; File
		jr z, _FileCheck
	if(FILE_DIRECTORY)
		jp nz,_BAD_ID ; don't handle other types for now
	call SkipDirEntry
	jr _FileSearch
_FileCheck:
	inc hl
#ifdef DEBUG
	push de
		push hl
			push bc
				push af
					push hl
						ld hl,NameMsg
						call DrawWrappedString
					pop hl
					call DrawWrappedString
					call Newline
					call FastCopy
				pop af
			pop bc
		pop hl
	pop de
#endif
	push hl
		push de
			call CmpStrings
		pop de
	pop hl
		jr z,_
	call SkipFileEntry
	jr _FileSearch
_	call SkipEntryName	; Found file
	push hl
		push de
			ld bc,5
			add hl,bc	; get parent Dir ID
			ld c,(hl)
			inc hl
			ld b,(hl)	; load it into bc
			ld hl,FSTmp
			ld e,(hl)
			inc hl
			ld d,(hl)
			ld a,d
			cp b
				jr nz,_
			ld a,e
			cp c
				jr nz,_
		pop de
	pop hl
	ld a, (hl) ; Flash page into A
#ifdef DEBUG
	push bc
		push hl
			push de
				push af
					ld hl,PageMsg
					call DrawWrappedString
				pop af
				push af
					call DispHexA
					call Newline
				pop af
			pop de
		pop hl
	pop bc
#endif
	inc hl
	ld e, (hl)
	inc hl
	ld d, (hl) ; Location in DE
	inc hl
	ld c, (hl)
	inc hl
	ld b, (hl) ; Size in BC
	push af
		xor a ; ld a,0
		cp c	; if c is not 0
			jr nz,_	; skip this
		cp b	; if b is 0 then go error
			jr z,_NULL_FILE
_	pop af
	out (6), a ; Set flash page
	ld h,a	; flash page in h
#ifdef DEBUG
	push de
		push bc
			push hl
				ld hl,AddressMsg
				call DrawWrappedString
				ld a,d
				call DispHexA
				ld a,e
				call DispHexA
				call Newline
			pop hl
		pop bc
	pop de
#endif
	return(SUCCESS)	; return with a success
_	pop de
	pop hl
	jp _FileSearch
_NOT_IN_DIR:
	return(FILE_NOT_IN_DIR)
_BAD_ID:
	return(BAD_ID)
_BAD_PATH:
	return(BAD_PATH)
_END_OF_TABLE:
	return(END_OF_FAT)
_NULL_FILE:
	pop af
	return(FILE_IS_NULL)
; Gets the pointer to the file in ix and de
GetPointer:
	call GetFilePointer
	inc de
	inc de
	push de
	pop ix
	ret
;
SkipDirEntry:
	call SkipEntryName
	inc hl
	inc hl; pass the Dir ID
	inc hl
	inc hl; pass the parent Dir ID
	ret
;
SkipFileEntry:
	ld a,(hl)
	call SkipEntryName
	ld b,7
_		inc hl
		djnz -_	;optimize this later
	; skip the rest of the data
	ret
; skips past the name and returns the location past the name in hl
SkipEntryName:
	ld a, 0
	push bc
		ld bc, 0FFFFh 
		cpir	; Move HL to the end of the name
	pop bc
	ret
; inputs	de = Pointer to path
; outputs	z  = true
;		nz = false
ContainsSlash:
	push de
_		ld a, (de)
		cp '/'
		jr z, ++_
		or a
		jr z, _
		inc de
		jr -_
_	cp 1
_	pop de
	ret
; checks to see if the directory exists
DirectoryCompare:
	ld b,d \ ld c,e
_		ld a, (de)
		or a
			jr z,+++_
		cp '/'
			jr z,_
		cp (hl)
			jr nz,++_
		inc hl
		inc de
		jr -_
_	inc de
	ld a, (hl)
	or a
		ret z
	cp 1
	ret
_	ld d,b \ ld e,c
	ret
_	ld d,b \ ld e,c
	cp 1
	ret
